package crontab

import (
	"fmt"
	"github.com/spf13/cast"
	"longmen/server/config/global"
	_const "longmen/server/pkg/common/helper/const"
	"longmen/server/pkg/db/mysql/models/models_main"
	"longmen/server/pkg/db/redis/cache"
	"strings"
	"time"
)

func LiveWatchStatSave() {
	//记录观众数
	ChannelIpStat()
	////记录观看时间
	DeviceWatchTime()
}

type StatUser struct {
	ID         int       `json:"id"`
	SourceKey  string    `json:"source_key"`
	Date       time.Time `json:"date"`
	SourceName string    `json:"source_name"`
	ActiveUser int       `json:"active_user"` // 活跃用户
}

func ChannelIpStat() {
	mp, err := cache.NewStatUserWatch().CountUniqueUsers()
	if err != nil {
		global.Log.Error("ChannelIpStat error: ", err)
		return
	}
	if len(mp) <= 0 {
		return
	}

	var channels []models_main.RegSource
	err = global.GetR().Model(&models_main.RegSource{}).Find(&channels).Error
	if err != nil {
		global.Log.Error("ChannelIpStat error:", err)
		return
	}

	var stUsers []models_main.StatUser
	err = global.GetR().Model(&models_main.StatUser{}).Where("date=?", time.Now().Format("2006-01-02")).Find(&stUsers).Error
	if err != nil {
		return
	}
	stUserMp := map[string]models_main.StatUser{}
	for i, user := range stUsers {
		stUserMp[user.SourceKey] = stUsers[i]
	}

	upStMp := map[int]int{}
	var upIds []string
	var insSlice []models_main.StatUser
	for channel, count := range mp {
		stUser, ok := stUserMp[channel]
		if ok {
			if int(count) > stUser.ActiveUser {
				upIds = append(upIds, cast.ToString(stUser.ID))
				upStMp[stUser.ID] = int(count)
			}
		} else {
			insSlice = append(insSlice, models_main.StatUser{
				SourceKey: channel,
				SourceName: func() string {
					for _, v := range channels {
						if v.SourceKey == channel {
							return v.SourceName
						}
					}
					return ""
				}(),
				ActiveUser: int(count),
				Date:       time.Now(),
			})
		}
	}
	if len(insSlice) > 0 {
		err = global.GetR().Model(&models_main.StatUser{}).Create(&insSlice).Error
		if err != nil {
			return
		}
	}
	if len(upIds) > 0 {
		// 构建 CASE 语句
		caseStmt := "CASE"
		for id, activeUserCount := range upStMp {
			caseStmt += fmt.Sprintf(" WHEN id = %d THEN %d", id, activeUserCount)
		}
		caseStmt += " ELSE active_user END"

		// 更新语句
		updateStmt := fmt.Sprintf("UPDATE %s SET active_user = %s WHERE id IN (%s)", (&models_main.StatUser{}).TableName(), caseStmt, strings.Join(upIds, ","))
		// 执行更新
		err = global.GetX().Exec(updateStmt).Error
		if err != nil {
			global.Log.Debug("cron ChannelIpStat Error: ", err)
		}
	}
}

func DeviceWatchTime() {
	//取出需要更新的直播间观看数据
	var cursor uint64 = 0
	var err error
	for {
		var res []string
		var nextCursor uint64
		res, nextCursor, err = global.GetRds().HScan(_const.LiveWatchUpdateList, cursor, "*", 1000).Result()
		if err != nil {
			global.Log.Debug("cron RoomWatchStatSave Error: ", err)
			continue
		}
		resMp := map[string]string{}
		for i := 0; i < len(res); i += 2 {
			field := res[i]
			value := res[i+1]
			resMp[field] = value
		}
		SaveDb(resMp)

		// 更新游标
		cursor = nextCursor
		if cursor <= 0 {
			break
		}
	}
}

func SaveDb(resMp map[string]string) {
	if len(resMp) <= 0 {
		return
	}
	//取出所有deviceId
	devIds := []string{}
	for k, _ := range resMp {
		devIds = append(devIds, k)
	}

	//查询是否有已经入库的数据
	var appds []models_main.AppDownload
	appMp := map[string]*models_main.AppDownload{}
	err := global.GetR().Table(models_main.AppDownload{}.TableName()+" use index(device_id)").Where("device_id IN ?", devIds).Select("id, device_id, duration").Find(&appds).Error
	if err != nil {
		global.Log.Debug("cron RoomWatchStatSave Error: ", err)
		return
	}
	for i, w := range appds {
		appMp[w.DeviceId] = &appds[i]
	}

	//分离插入和更新
	var insWs []models_main.AppDownload
	var upIds []string
	upWsMp := map[int]int{}
	var wd cache.LiveWatchDevice
	for devId, wds := range resMp {
		wd = *wd.Unmarshal(wds)
		app, ok := appMp[devId]
		if ok {
			if wd.Duration > app.Duration {
				upIds = append(upIds, cast.ToString(app.Id))
				upWsMp[int(app.Id)] = wd.Duration
			}
			global.GetRds().HDel(_const.LiveWatchUpdateList, devId)
		} else {
			//app.Duration = accDur
			//insWs = append(insWs, *app)
		}
	}

	//入库
	if len(insWs) > 0 {
		err = global.GetX().Save(&insWs).Error
		if err != nil {
			global.Log.Debug("cron RoomWatchStatSave Error: ", err)
		}
	}

	if len(upWsMp) > 0 {
		// 构建 CASE 语句
		caseStmt := "CASE"
		for id, duration := range upWsMp {
			caseStmt += fmt.Sprintf(" WHEN id = %d THEN %d", id, duration)
		}
		caseStmt += " ELSE duration END"

		// 更新语句
		updateStmt := fmt.Sprintf("UPDATE %s SET duration = %s WHERE id IN (%s)", models_main.AppDownload{}.TableName(), caseStmt, strings.Join(upIds, ","))
		// 执行更新
		err = global.GetX().Exec(updateStmt).Error
		if err != nil {
			global.Log.Debug("cron RoomWatchStatSave Error: ", err)
		}
	}
}
